package com.example.myapplication2;

import java.util.*;
import java.lang.*;
import java.nio.*;

public class myBuf {
    byte[] buf = new byte[0];
    int dataPos = 0;
    int startPos = 0;

    myBuf() {
    }

    myBuf(int l) {
        buf = new byte[l];
    }

    myBuf(byte[] a) {
        buf = a;
        dataPos = a.length;
    }

    byte[] get() {
        byte[] r = new byte[dataPos - startPos];
        System.arraycopy(buf, startPos, r, 0, dataPos - startPos);
        return r;
    }

    void set(byte[] a) {
        buf = a;
        startPos = 0;
        dataPos = a.length;
    }

    void clear() {
        startPos = dataPos = 0;
    }

    void addLeft(byte[] a) {
        if (startPos >= a.length) {
            System.arraycopy(a, 0, buf, startPos - a.length, a.length);
            startPos -= a.length;
        } else {
            byte[] tt = get();
            clear();
            append(a);
            append(tt);
        }
    }

    int size() {
        return dataPos - startPos;
    }

    void append(byte[] a) {
        if (a.length + dataPos <= buf.length) {
            System.arraycopy(a, 0, buf, dataPos, a.length);
            dataPos += a.length;
            return;
        }

        if (a.length + dataPos <= (int) (buf.length * 0.2)) {
            byte[] r = new byte[(int) (buf.length * 0.2)];
            System.arraycopy(buf, startPos, r, 0, dataPos - startPos);
            System.arraycopy(a, 0, r, dataPos - startPos, a.length);
            dataPos = dataPos - startPos + a.length;
            startPos = 0;
            buf = r;
            return;
        }

        if (a.length + dataPos - startPos <= buf.length) {
            byte[] r = new byte[buf.length];
            System.arraycopy(buf, startPos, r, 0, dataPos - startPos);
            System.arraycopy(a, 0, r, dataPos - startPos, a.length);
            dataPos = dataPos - startPos + a.length;
            startPos = 0;
            buf = r;
            return;
        }
        int newLe = 2 * buf.length;
        if (dataPos - startPos + a.length > newLe)
            newLe = 2 * a.length;
        byte[] r = new byte[newLe];
        System.arraycopy(buf, startPos, r, 0, dataPos - startPos);
        System.arraycopy(a, 0, r, dataPos - startPos, a.length);
        dataPos = dataPos - startPos + a.length;
        startPos = 0;
        buf = r;
    }

    byte[] readArr(int l) {
        if (l < 0)
            l = 0;
        if (dataPos - startPos < l)
            l = dataPos - startPos;
        byte[] r = new byte[l];
        System.arraycopy(buf, startPos, r, 0, l);
        startPos += l;
        return r;
    }

    void writeArr(byte[] a) {
        append(a);
    }

    long readQ() {
        long a = ByteBuffer.wrap(buf, startPos, 8).order(ByteOrder.nativeOrder()).getLong();
        startPos += 8;
        return a;
    }

    void writeQ(long a) {
        byte[] t = ByteBuffer.allocate(8).order(ByteOrder.nativeOrder()).putLong(a).array();
        append(t);
    }

    void writeFloat(float a) {
        byte[] t = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putFloat(a).array();
        append(t);
    }

    float readFloat() {
        float a = ByteBuffer.wrap(buf, startPos, 4).order(ByteOrder.nativeOrder()).getFloat();
        startPos += 4;
        return a;
    }

    public int readByte() {
        byte b = buf[startPos];
        startPos++;
        if (b < 0)
            return b + 256;
        return b;
    }

    void writeByte(int a) {
        byte b = (byte) a;
        byte[] xx = new byte[1];
        xx[0] = b;
        append(xx);
    }

    public int readWord() {
        short a = ByteBuffer.wrap(buf, startPos, 2).order(ByteOrder.nativeOrder()).getShort();
        startPos += 2;
        if (a < 0)
            return a + 65536;
        return a;
    }

    public void writeWord(int a) {
        short s = (short) a;
        byte[] t = ByteBuffer.allocate(2).order(ByteOrder.nativeOrder()).putShort(s).array();
        append(t);
    }

    int readDWord() {
        int a = ByteBuffer.wrap(buf, startPos, 4).order(ByteOrder.nativeOrder()).getInt();
        startPos += 4;
        return a;
    }

    public void writeDWord(int s) {
        byte[] t = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(s).array();
        append(t);
    }

    public void writeDouble(double s) {
        byte[] t = ByteBuffer.allocate(8).order(ByteOrder.nativeOrder()).putDouble(s).array();
        append(t);
    }
}
